let offsetX = 0

// 节流
function throttleRAF(callback) {
  let block = false;
  return function (...args) {
    if (!block) {
      block = true;
      requestAnimationFrame(() => {
        callback.apply(this, args);
        block = false;
      });
    }
  };
}

/**
 * 左右拖动逻辑
 * @param dividerDom {HTMLElement} 触发拖拽元素
 * */
function initDrag(dividerDom) {
  let isDragging = false
  dividerDom.addEventListener('mousedown', (e) => {
    isDragging = true
    const dividerRect = dividerDom.getBoundingClientRect()
    offsetX = e.clientX - dividerRect.left
  })

  document.addEventListener('mousemove', throttleRAF((e) => {
    if (isDragging) {
      const bodyWidth = document.body.offsetWidth
      // left也就是textarea的宽度
      const left = e.clientX - offsetX

      if (left <= 200 || (bodyWidth - left) <= 200) return

      const root = document.getElementById('root')
      const textareaWrap = document.getElementsByClassName('textarea-wrap')
      const textarea = document.getElementById('textarea')
      // textarea容器宽度 = textarea宽度 + divider宽度
      const textareaWrapWidth = left + 8
      textareaWrap[0].style.width = textareaWrapWidth + 'px'
      textarea.style.width = left + 'px'
      root.style.width = bodyWidth - textareaWrapWidth + 'px'
    }
  }))

  document.addEventListener('mouseup', () => {
    isDragging = false
    offsetX = 0
  })
}

function _json_parse(str) {
  try {
    return JSON.parse(decodeURIComponent(str))
  } catch (e) {
    return str
  }
}

/**
 * 创建dom元素
 *
 * @param type 创建的dom标签类型
 * @param props 所创建dom上的属性
 * @param children 所创建dom的子元素
 * */
function _createElement(type, props, ...children) {
  const dom = document.createElement(type || 'div')
  if (props) {
    for (const key in props) {
      dom.setAttribute(key, props[key])
    }
  }
  if (children) {
    for (const child of children) {
      if (child === null || child === void 0) {
        dom.appendChild(document.createTextNode(''))
      } else if (
        typeof child === 'string' ||
        typeof child === 'number' ||
        typeof child === 'boolean'
      ) {
        dom.appendChild(document.createTextNode(child))
      } else if (typeof child === 'object') {
        dom.appendChild(child)
      } else {
        // 其余类型使用toString转换
        dom.appendChild(document.createTextNode(child.toString()))
      }
    }
  }

  return dom
}

/**
 * 校验是否是 url，如果是返回 url 解析对象，如果不是返回原字符串
 * */
function validateUrl(url) {
  try {
    // 创建一个 url 对象
    let urlObj = new URL(url)
    const {search, hash} = urlObj
    let searchParams = urlObj.searchParams

    // 如果search为空，就是没有参数，没有参数不用解析，直接返回原字符串
    if (!search) return url

    // 如果有 hash 说明参数中包含了 # 号，就不能用 URL.searchParams 对象了，要用 URLSearchParams
    if (hash) {
      const index = url.indexOf('?')
      const searchStr = url.substring(index)
      searchParams = new URLSearchParams(searchStr)
    }

    const rstObj = {}
    // 增加指定属性
    rstObj.origin = urlObj.origin
    rstObj.port = urlObj.port
    rstObj.pathname = urlObj.pathname
    // 参数对象
    const urlQuery = {}

    for (const [k, v] of searchParams) {
      // 处理 v 属性 v参数字段是由$符拼接的字符串
      if (k === 'v') {
        if (v.indexOf('$') !== -1) {
          const vals = v.split('$')
          urlQuery[k] = vals.reduce((rst, item) => {
            const [key, value] = item.split('=')
            // 处理 p0 属性，它是一个 json 字符串
            if (key === 'p0') {
              // debugger
              rst[key] = _json_parse(value)
            } else {
              rst[key] = value
            }
            return rst
          }, {})
        } else {
          urlQuery[k] = v
        }
      } else {
        urlQuery[k] = v
      }
    }
    rstObj.query = urlQuery

    return rstObj
  } catch (e) {
    // 解析失败返回原字符串
    return url
  }
}

/**
 *  校验是否是合法的 json 字符串，如果是返回解析后的对象，如果不是返回原字符串
 * */
function validateJson(str) {
  try {
    return str === 'null' ? str : JSON.parse(str)
  } catch (e) {
    // console.log('校验json失败', str, e)
    return str
  }
}

/**
 * 校验是否是对象或者数组的字符串
 * */
function validateObjStr(str) {
  try {
    return new Function(`return ${str}`)()
  } catch (e) {
    return str
  }
}

/**
 * 统一对象属性顺序
 * @return arr 对象属性组成的数组，按一定顺序的
 * */
function sortObj(obj) {
  return Object.keys(obj).sort()
}